home *** CD-ROM | disk | FTP | other *** search
- /* Parser for SSS */
- /* Tue,30 Jul 1991 */
- /* Copyright C.T.Stretch 1991 */
-
- #include "ssshdr.h"
- #include <signal.h>
- #include <setjmp.h>
- #include <float.h>
-
- #define CHK(c) if(*nextc++!=c) longjmp(env,2)
- #define DO(f) CHK('(');val=f(rexp(0));CHK(')');break
- #define R(a,b) CHK('[');a=iexp(0);CHK(',');b=iexp(0);CHK(']')
- #define DR R(x0,y0);R(x1,y1)
-
- static jmp_buf env;
- static double sx,sxx;
- static int nx,x0,y0,x1,y1;
- int vx,vy;
- double value;
- char *expr;
- BOOL perr;
- static char *nextc;
-
- static double rexp(int);
- static int iexp(int);
-
- static double cell(int x,int y)
- { entry *cb;
- fixed=0;
- if(x<0 || x>=ncols || y<0 || y>=nrows)
- { errno=1;
- return 1;
- }
- cb=sheet[x+NCOLS*y];
- if(!cb||cb->t<FINT||cb->a||cb->p)
- { errno=1;
- return 1;
- }
- return cb->v;
- }
-
- static double cmax()
- { entry *cb;
- int x,y;
- double best=-DBL_MAX;
- fixed=0;
- if(x0<0 || x1>=ncols || y0<0 || y1>=nrows)
- { errno=1;
- return 0;
- }
- for(x=x0;x<=x1;x++) for(y=y0;y<=y1;y++)
- { cb=sheet[x+NCOLS*y];
- if(cb&&cb->t>=FINT&&!(cb->a||cb->p))
- { if(cb->v>best) best=cb->v;
- }
- }
- if(best==-DBL_MAX) {errno=1;return 0;}
- return best;
- }
-
- static double cmin()
- { entry *cb;
- int x,y;
- double best=DBL_MAX;
- fixed=0;
- if(x0<0 || x1>=ncols || y0<0 || y1>=nrows)
- { errno=1;
- return 0;
- }
- for(x=x0;x<=x1;x++) for(y=y0;y<=y1;y++)
- { cb=sheet[x+NCOLS*y];
- if(cb&&cb->t>=FINT&&!(cb->a||cb->p))
- { if(cb->v<best) best=cb->v;
- }
- }
- if(best==DBL_MAX) {errno=1;return 0;}
- return best;
- }
-
- static void countup()
- { entry *cb;
- int x,y;
- fixed=0;
- nx=0;sx=0;sxx=0;
- if(x0<0 || x1>=ncols || y0<0 || y1>=nrows)
- { errno=1;
- return ;
- }
- for(x=x0;x<=x1;x++) for(y=y0;y<=y1;y++)
- { cb=sheet[x+NCOLS*y];
- if(cb&&cb->t>=FINT&&!(cb->p||cb->a))
- { nx++;sx+=cb->v;sxx+=cb->v*cb->v;
- }
- }
- return ;
- }
-
- static int ibexp()
- { int val;
- switch(*nextc)
- { case '(':nextc++;
- val=iexp(0);
- CHK(')');
- break;
- case '+':nextc++;
- val=iexp(0);
- break;
- case '-':nextc++;
- val=-iexp(0);
- break;
- case 'x':nextc++;val=vx;break;
- case 'y':nextc++;val=vy;break;
- default:if(isdigit(*nextc)) val=(int)strtol(nextc,&nextc,10);
- else longjmp(env,2);
- }
- return val;
- }
-
- static int iexp(int n)
- { int a=ibexp();
- for(;;) switch(*nextc)
- { case '+':if(n>=1) return a;nextc++;a+=iexp(1);break;
- case '-':if(n>=1) return a;nextc++;a-=iexp(1);break;
- case '*':if(n>=2) return a;nextc++;a*=iexp(2);break;
- case '/':if(n>=2) return a;nextc++;a/=iexp(2);break;
- case ' ':nextc++;break;
- default :return a;
- }
- }
-
- static double rbexp()
- { double val;
- int i;
- switch(*nextc)
- { case '(':nextc++;
- val=rexp(0);
- CHK(')');
- break;
- case '[':nextc++;
- i=iexp(0);
- CHK(',');
- val=cell(i,iexp(0));
- CHK(']');
- break;
- case '+':nextc++;
- val=rexp(0);
- break;
- case '-':nextc++;
- val=-rexp(0);
- break;
- case '.':val=strtod(nextc,&nextc);break;
- default :if(isdigit(*nextc)) { val=strtod(nextc,&nextc);break;}
- switch((int)strtol(nextc,&nextc,36))
- { case 33:val=vx;break;
- case 34:val=vy;break;
- case 36959:DO(sin);
- case 16444:DO(cos);
- case 37967:DO(tan);
- case 28096:DO(log);
- case 19357:DO(exp);
- case 1341065:DO(sqrt);
- case 1034:CHK('(');val=rexp(0);CHK(')');val=val*val;break;
- case 578685:DO(ceil);
- case 26206011:DO(floor);
- case 46509097:CHK('(');val=floor(rexp(0)+0.5);CHK(')');break;
- case 503519:DO(asin);
- case 483004:DO(acos);
- case 504527:DO(atan);
- case 18162974:CHK('(');val=rexp(0);;CHK(',');
- val=atan2(val,rexp(0));
- CHK('(');break;
- case 1330541:DO(sinh);
- case 592001:DO(cosh);
- case 1366829:DO(tanh);
- case 37390:DR;countup();val=sx;break;
- case 21314873:DR;countup();val=nx;break;
- case 13384:DO(fabs);
- case 1044959:DR;countup();val=sx/nx;break;
- case 37309:DR;countup();
- val=sqrt((nx*sxx-sx*sx)/(nx*(nx-1)));break;
- case 33421:DR;countup();
- val=sqrt(sxx-sx*sx/nx);break;
- case 918:val=4*atan(1);break;
- case 14:val=exp(1);break;
- case 28905:DR;val=cmax();break;
- case 29183:DR;val=cmin();break;
- default:longjmp(env,2);
- }
- break;
- }
- return val;
- }
-
- static double rexp(int n)
- { double a=rbexp();
- for(;;) switch(*nextc)
- { case '+':if(n>=1) return a;nextc++;a+=rexp(1);break;
- case '-':if(n>=1) return a;nextc++;a-=rexp(1);break;
- case '*':if(n>=2) return a;nextc++;a*=rexp(2);break;
- case '/':if(n>=2) return a;nextc++;a/=rexp(2);break;
- case '^':if(n>=3) return a;nextc++;a=pow(a,rexp(4));break;
- case ' ':nextc++;break;
- default :return a;
- }
- }
-
- static void badfpe(int snag)
- { if(snag==SIGFPE) longjmp(env,1);
- }
-
- void eval()
- { int e;
- nextc=expr;
- errno=0;
- fixed=1;
- if(e=setjmp(env))
- { if(e==1) { errno=1;perr=0;} else perr=1;
- fixed=0;return;
- }
- signal(SIGFPE,badfpe);
- value=rexp(0);
- perr=*nextc;
- signal(SIGFPE,SIG_DFL);
- }
-